﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using r4u.data.access.layer;
using r4u.data.access.layer.RECRUIT;

namespace r4u.business.logic.layer.RECRUIT
{
    public class Candidate
    {
        #region Local Variables
        public string Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string PictureURL { get; set; }
        public string ProfileURL { get; set; }
        public string Email { get; set; }
        public List<Skill> Skills { get; set; }
        public List<Certification> Certifications { get; set; }
        public List<Project> Projects { get; set; }
        public decimal Experience { get; set; }
        public string CountryCode { get; set; }
        public int Age { get; set; }
        public List<EducationLevel> EducationLevels;
        public string Industry { get; set; }
        public int NoOfRecommandations { get; set; }
        public string Headline { get; set; }
        public string Summary { get; set; }
        public string Trial = string.Empty;
        public List<Education> Educations { get; set; }
        public List<Position> Positions { get; set; }
        public List<Recommandation> Recommandations { get; set; }
        #endregion

        #region Methods
        public Candidate(XmlDocument xmlDoc)
        {
            this.SetProfileData(xmlDoc);
            this.Industry = this.GetIndustry(xmlDoc);
            this.Skills = this.LoadSkills(xmlDoc);
            this.Certifications = this.LoadCertifications(xmlDoc);
            this.Projects = this.LoadProjects(xmlDoc);
            this.Experience = this.GetExperience(xmlDoc);
            this.CountryCode = this.GetCountry(xmlDoc);
            this.Age = this.GetAge(xmlDoc);
            this.EducationLevels = this.GetEducationLevels(xmlDoc);
            this.Educations = this.GetEducations(xmlDoc);
            this.Positions = this.GetPositions(xmlDoc);
            this.Recommandations = this.GetRecommandations(xmlDoc);
        }

        private void SetProfileData(XmlDocument xmlDoc)
        {

            if (xmlDoc.SelectSingleNode("//id") != null)
                this.Id = xmlDoc.SelectSingleNode("//id").InnerText;
            else
                this.Id = string.Empty;

            if (xmlDoc.SelectSingleNode("//first-name") != null)
                this.FirstName = xmlDoc.SelectSingleNode("//first-name").InnerText;
            else
                this.FirstName = string.Empty;


            if (xmlDoc.SelectSingleNode("//last-name") != null)
                this.LastName = xmlDoc.SelectSingleNode("//last-name").InnerText;
            else
                this.LastName = string.Empty;


            if (xmlDoc.SelectSingleNode("//picture-url") != null)
                this.PictureURL = xmlDoc.SelectSingleNode("//picture-url").InnerText;
            else
                this.PictureURL = string.Empty;

            if (xmlDoc.SelectSingleNode("//public-profile-url") != null)
                this.ProfileURL = xmlDoc.SelectSingleNode("//public-profile-url").InnerText;
            else
                this.ProfileURL = string.Empty;


            if (xmlDoc.SelectSingleNode("//email-address") != null)
                this.Email = xmlDoc.SelectSingleNode("//email-address").InnerText;
            else
                this.Email = string.Empty;

            if (xmlDoc.SelectSingleNode("//num-recommenders") != null)
                this.NoOfRecommandations = Convert.ToInt32(xmlDoc.SelectSingleNode("//num-recommenders").InnerText);
            else
                this.NoOfRecommandations = 0;

            if (xmlDoc.SelectSingleNode("//headline") != null)
                this.Headline = xmlDoc.SelectSingleNode("//headline").InnerText;
            else
                this.Headline = string.Empty;


            if (xmlDoc.SelectSingleNode("//summary") != null)
                this.Summary = xmlDoc.SelectSingleNode("//summary").InnerText;
            else
                this.Summary = string.Empty;

        }

        private string GetIndustry(XmlDocument xmlDoc)
        {
            XmlNode industry = xmlDoc.SelectSingleNode("//person/industry");

            if (industry != null)
                return industry.InnerText;
            else
                return string.Empty;
        }

        private List<EducationLevel> GetEducationLevels(XmlDocument xmlDoc)
        {
            List<EducationLevel> list = new List<EducationLevel>();
            XmlNodeList educations = xmlDoc.SelectNodes("/person/educations/education");

            foreach (XmlNode education in educations)
            {
                string name = education["degree"].InnerText;

                switch (name)
                {
                    case "High School":
                        list.Add(EducationLevel.HighSchool);
                        break;
                    case "Associate's Degree":
                        list.Add(EducationLevel.AssociateDegree);
                        break;
                    case "Bachelor's Degree":
                    case "Bachelor of Science (B.Sc.) Hons":
                    case "Bachelor of Science (BSc)":
                    case "Bsc Engineering":
                    case "Bachelor of Science":
                    case "Bachelor of Science (B.Sc.)":
                        list.Add(EducationLevel.Bsc);
                        break;
                    case "Master's Degree":
                        list.Add(EducationLevel.Msc);
                        break;
                    case "Master of Business Administration (M.B.A.)":
                        list.Add(EducationLevel.MBA);
                        break;
                    case "Juris Doctor (J.D.)":
                        list.Add(EducationLevel.JD);
                        break;
                    case "Doctor of Medicine (M.D.)":
                        list.Add(EducationLevel.MD);
                        break;
                    case "Doctor of Philosophy (Ph.D.)":
                        list.Add(EducationLevel.PHD);
                        break;
                    case "Engineer's Degree":
                        list.Add(EducationLevel.EngineersDegree);
                        break;
                    default:
                        list.Add(EducationLevel.Other);
                        break;
                }
            }
            return list;
        }

        private List<Skill> LoadSkills(XmlDocument xmlDoc)
        {
            XmlNodeList skills = xmlDoc.SelectNodes("/person/skills/skill");
            List<Skill> Skills = new List<Skill>();

            foreach (XmlNode skill in skills)
            {
                int Id = Int32.Parse(skill["id"].InnerText);
                string Name = skill["skill"].InnerText;
                Skills.Add(new Skill(Id, Name));
            }

            return Skills;
        }

        private List<Certification> LoadCertifications(XmlDocument xmlDoc)
        {
            XmlNodeList certifications = xmlDoc.SelectNodes("/person/certifications/certification");
            List<Certification> Certifications = new List<Certification>();

            foreach (XmlNode certification in certifications)
            {
                int Id = Int32.Parse(certification["id"].InnerText);
                string Name = certification["name"].InnerText;
                Certifications.Add(new Certification(Id, Name));
            }

            return Certifications;
        }

        private List<Project> LoadProjects(XmlDocument xmlDoc)
        {
            XmlNodeList projects = xmlDoc.SelectNodes("/person/projects/project");
            List<Project> Projects = new List<Project>();

            foreach (XmlNode project in projects)
            {
                int Id = Int32.Parse(project["id"].InnerText);
                string Name = project["name"].InnerText;
                string Description = project["description"].InnerText;

                Projects.Add(new Project(Id, Name, Description));
            }

            return Projects;
        }

        private decimal GetExperience(XmlDocument xmlDoc)
        {
            XmlNodeList positions = xmlDoc.SelectNodes("/person/positions/position");
            DateTime zeroTime = new DateTime(1, 1, 1);
            int experience = 0;
            int start_year, start_month, finish_year, finish_month;
            DateTime start, finish;
            TimeSpan span;


            foreach (XmlNode position in positions)
            {
                string is_current = position["is-current"].InnerText;

                if (is_current.Equals("true"))
                {
                    start_year = Int32.Parse(position["start-date"]["year"].InnerText);
                    start_month = Int32.Parse(position["start-date"]["month"].InnerText);
                    start = new DateTime(start_year, start_month, 1);
                    finish = DateTime.Now;
                }
                else
                {
                    start_year = Int32.Parse(position["start-date"]["year"].InnerText);
                    start_month = Int32.Parse(position["start-date"]["month"].InnerText);
                    finish_year = Int32.Parse(position["end-date"]["year"].InnerText);
                    finish_month = Int32.Parse(position["end-date"]["month"].InnerText);
                    start = new DateTime(start_year, start_month, 1);
                    finish = new DateTime(finish_year, finish_month, 1);
                }

                span = finish - start;
                int years = (zeroTime + span).Year - 1;
                experience += years;
            }
            return experience;
        }

        public string GetCountry(XmlDocument xmlDoc)
        {
            XmlNodeList countries = xmlDoc.SelectNodes("/person/location/country");

            foreach (XmlNode country in countries)
            {
                return country["code"].InnerText.ToUpper();
            }
            return string.Empty;
        }

        public int GetAge(XmlDocument xmlDoc)
        {
            XmlNode birth_year = xmlDoc.SelectSingleNode("//person/date-of-birth/year");
            if (birth_year != null)
            {
                return DateTime.Now.Year - Int32.Parse(birth_year.InnerText) + 1;
            }
            else
            {
                return 0;
            }
        }

        public string GetIndustry(string code)
        {
            switch (code)
            {
                case "47":
                    return "Accounting";
                case "94":
                    return "Airlines/Aviation";
                case "120":
                    return "Alternative Dispute Resolution";
                case "125":
                    return "Alternative Medicine";
                case "127":
                    return "Animation";
                case "19":
                    return "Apparel & Fashion";
                case "50":
                    return "Architecture & Planning";
                case "111":
                    return "Arts and Crafts";
                case "53":
                    return "Automotive";
                case "52":
                    return "Aviation & Aerospace";
                case "41":
                    return "Banking";
                case "12":
                    return "Biotechnology";
                case "36":
                    return "Broadcast Media";
                case "49":
                    return "Building Materials";
                case "138":
                    return "Business Supplies and Equipment";
                case "129":
                    return "Capital Markets";
                case "54":
                    return "Chemicals";
                case "90":
                    return "Civic & Social Organization";
                case "51":
                    return "Civil Engineering";
                case "128":
                    return "Commercial Real Estate";
                case "118":
                    return "Computer & Network Security";
                case "109":
                    return "Computer Games";
                case "3":
                    return "Computer Hardware";
                case "5":
                    return "Computer Networking";
                case "4":
                    return "Computer Software";
                case "48":
                    return "Construction";
                case "24":
                    return "Consumer Electronics";
                case "25":
                    return "Consumer Goods";
                case "91":
                    return "Consumer Services";
                case "18":
                    return "Cosmetics";
                case "65":
                    return "Dairy";
                case "1":
                    return "Defense & Space";
                case "99":
                    return "Design";
                case "69":
                    return "Education Management";
                case "132":
                    return "E-Learning";
                case "112":
                    return "Electrical/Electronic Manufacturing";
                case "28":
                    return "Entertainment";
                case "86":
                    return "Environmental Services";
                case "110":
                    return "Events Services";
                case "76":
                    return "Executive Office";
                case "122":
                    return "Facilities Services";
                case "63":
                    return "Farming";
                case "43":
                    return "Financial Services";
                case "38":
                    return "Fine Art";
                case "66":
                    return "Fishery";
                case "34":
                    return "Food & Beverages";
                case "23":
                    return "Food Production";
                case "101":
                    return "Fund-Raising";
                case "26":
                    return "Furniture";
                case "29":
                    return "Gambling & Casinos";
                case "145":
                    return "Glass, Ceramics & Concrete";
                case "75":
                    return "Government Administration";
                case "148":
                    return "Government Relations";
                case "140":
                    return "Graphic Design";
                case "124":
                    return "Health, Wellness and Fitness";
                case "68":
                    return "Higher Education";
                case "14":
                    return "Hospital & Health Care";
                case "31":
                    return "Hospitality";
                case "137":
                    return "Human Resources";
                case "134":
                    return "Import and Export";
                case "88":
                    return "Individual & Family Services";
                case "147":
                    return "Industrial Automation";
                case "84":
                    return "Information Services";
                case "96":
                    return "Information Technology and Services";
                case "42":
                    return "Insurance";
                case "74":
                    return "International Affairs";
                case "141":
                    return "International Trade and Development";
                case "6":
                    return "Internet";
                case "45":
                    return "Investment Banking";
                case "46":
                    return "Investment Management";
                case "73":
                    return "Judiciary";
                case "77":
                    return "Law Enforcement";
                case "9":
                    return "Law Practice";
                case "10":
                    return "Legal Services";
                case "72":
                    return "Legislative Office";
                case "30":
                    return "Leisure, Travel & Tourism";
                case "85":
                    return "Libraries";
                case "116":
                    return "Logistics and Supply Chain";
                case "143":
                    return "Luxury Goods & Jewelry";
                case "55":
                    return "Machinery";
                case "11":
                    return "Management Consulting";
                case "95":
                    return "Maritime";
                case "97":
                    return "Market Research";
                case "80":
                    return "Marketing and Advertising";
                case "135":
                    return "Mechanical or Industrial Engineering";
                case "126":
                    return "Media Production";
                case "17":
                    return "Medical Devices";
                case "13":
                    return "Medical Practice";
                case "139":
                    return "Mental Health Care";
                case "71":
                    return "Military";
                case "56":
                    return "Mining & Metals";
                case "35":
                    return "Motion Pictures and Film";
                case "37":
                    return "Museums and Institutions";
                case "115":
                    return "Music";
                case "114":
                    return "Nanotechnology";
                case "81":
                    return "Newspapers";
                case "100":
                    return "Non-Profit Organization Management";
                case "57":
                    return "Oil & Energy";
                case "113":
                    return "Online Media";
                case "123":
                    return "Outsourcing/Offshoring";
                case "87":
                    return "Package/Freight Delivery";
                case "146":
                    return "Packaging and Containers";
                case "61":
                    return "Paper & Forest Products";
                case "39":
                    return "Performing Arts";
                case "15":
                    return "Pharmaceuticals";
                case "131":
                    return "Philanthropy";
                case "136":
                    return "Photography";
                case "117":
                    return "Plastics";
                case "107":
                    return "Political Organization";
                case "67":
                    return "Primary/Secondary Education";
                case "83":
                    return "Printing";
                case "105":
                    return "Professional Training & Coaching";
                case "102":
                    return "Program Development";
                case "79":
                    return "Public Policy";
                case "98":
                    return "Public Relations and Communications";
                case "78":
                    return "Public Safety";
                case "82":
                    return "Publishing";
                case "62":
                    return "Railroad Manufacture";
                case "64":
                    return "Ranching";
                case "44":
                    return "Real Estate";
                case "40":
                    return "Recreational Facilities and Services";
                case "89":
                    return "Religious Institutions";
                case "144":
                    return "Renewables & Environment";
                case "70":
                    return "Research";
                case "32":
                    return "Restaurants";
                case "27":
                    return "Retail";
                case "121":
                    return "Security and Investigations";
                case "7":
                    return "Semiconductors";
                case "58":
                    return "Shipbuilding";
                case "20":
                    return "Sporting Goods";
                case "33":
                    return "Sports";
                case "104":
                    return "Staffing and Recruiting";
                case "22":
                    return "Supermarkets";
                case "8":
                    return "Telecommunications";
                case "60":
                    return "Textiles";
                case "130":
                    return "Think Tanks";
                case "21":
                    return "Tobacco";
                case "108":
                    return "Translation and Localization";
                case "92":
                    return "Transportation/Trucking/Railroad";
                case "59":
                    return "Utilities";
                case "106":
                    return "Venture Capital & Private Equity";
                case "16":
                    return "Veterinary";
                case "93":
                    return "Warehousing";
                case "133":
                    return "Wholesale";
                case "142":
                    return "Wine and Spirits";
                case "119":
                    return "Wireless";
                case "103":
                    return "Writing and Editing";
                default:
                    return string.Empty;
            }
        }

        public EducationLevel GetEducation(string level)
        {
            switch (level)
            {
                case "High School":
                    return EducationLevel.HighSchool;
                case "Associate's Degree":
                    return EducationLevel.AssociateDegree;
                case "Bachelor's Degree":
                case "Bachelor of Science (B.Sc.) Hons":
                case "Bachelor of Science (BSc)":
                case "Bsc Engineering":
                case "Bachelor of Science":
                case "Bachelor of Science (B.Sc.)":
                    return EducationLevel.Bsc;
                case "Master's Degree":
                    return EducationLevel.Msc;
                case "Master of Business Administration (M.B.A.)":
                    return EducationLevel.MBA;
                case "Juris Doctor (J.D.)":
                    return EducationLevel.JD;
                case "Doctor of Medicine (M.D.)":
                    return EducationLevel.MD;
                case "Doctor of Philosophy (Ph.D.)":
                    return EducationLevel.PHD;
                case "Engineer's Degree":
                    return EducationLevel.EngineersDegree;
                default:
                    return EducationLevel.Other;
            }
        }

        public bool ContainsSkill(string skill)
        {
            foreach (Skill s in this.Skills)
            {
                if (skill.ToLower().Equals(s.Name.ToLower()))
                    return true;
            }
            return false;
        }

        public List<Education> GetEducations(XmlDocument xmlDoc)
        {
            List<Education> list = new List<Education>();
            XmlNodeList educations = xmlDoc.SelectNodes("/person/educations/education");

            foreach (XmlNode education in educations)
            {
                Education edu = new Education();
                edu.School = education["school-name"] != null ? education["school-name"].InnerText : string.Empty;
                edu.Notes = education["notes"] != null ? education["notes"].InnerText : string.Empty;
                edu.Degree = education["degree"] != null ? education["degree"].InnerText : string.Empty;
                edu.Field = education["field-of-study"] != null ? education["field-of-study"].InnerText : string.Empty;
                edu.Start = education["start-date"]["year"] != null ? education["start-date"]["year"].InnerText : string.Empty;
                edu.End = education["end-date"]["year"] != null ? education["end-date"]["year"].InnerText : string.Empty;
                list.Add(edu);
            }
            return list;
        }

        public List<Position> GetPositions(XmlDocument xmlDoc)
        {
            List<Position> list = new List<Position>();
            XmlNodeList positions = xmlDoc.SelectNodes("/person/positions/position");

            foreach (XmlNode position in positions)
            {
                Position pos = new Position();
                pos.Title = position["title"] != null ? position["title"].InnerText : string.Empty;
                pos.Company = position["company"]["name"] != null ? position["company"]["name"].InnerText : string.Empty;
                pos.Start = position["start-date"]["year"] != null ? position["start-date"]["year"].InnerText : string.Empty;
                pos.End = position["end-date"] != null ? position["end-date"]["year"].InnerText : "Present";
                list.Add(pos);
            }
            return list;
        }


        public List<Recommandation> GetRecommandations(XmlDocument xmlDoc)
        {
            List<Recommandation> list = new List<Recommandation>();
            XmlNodeList recommandations = xmlDoc.SelectNodes("/person/recommendations-received/recommendation");

            foreach (XmlNode recommandation in recommandations)
            {
                Recommandation r = new Recommandation();
                r.Text = recommandation["recommendation-text"] != null ? recommandation["recommendation-text"].InnerText : string.Empty;
                r.FirstName = recommandation["recommender"]["first-name"] != null ? recommandation["recommender"]["first-name"].InnerText : string.Empty;
                r.LastName = recommandation["recommender"]["last-name"] != null ? recommandation["recommender"]["last-name"].InnerText : string.Empty;
                list.Add(r);
            }
            return list;
        }


        #endregion


        public bool CheckQualify(string vacancyId)
        {
            VacancyDAO vacancyDao = new VacancyDAO();
            VACANCY vacancy = vacancyDao.GetVacancyWithSkills(vacancyId);

            #region Checking Location
            if (!string.IsNullOrEmpty(vacancy.location_of_applicant))
            {
                if (!this.CountryCode.Equals(vacancy.location_of_applicant))
                {
                    return false;
                }
            } 
            #endregion

            #region Checking Experience
            if (vacancy.experience_from.HasValue)
            {
                if (this.Experience < vacancy.experience_from)
                {
                    return false;
                }
            }

            if (vacancy.experience_to.HasValue)
            {
                if (this.Experience > vacancy.experience_to)
                {
                    return false;
                }
            } 
            #endregion

            #region Checking Age
            if (vacancy.age_from.HasValue)
            {
                if (this.Age < vacancy.age_from)
                {
                    return false;
                }
            }

            if (vacancy.age_to.HasValue)
            {
                if (this.Age > vacancy.age_to)
                {
                    return false;
                }
            } 
            #endregion

            #region Checking Industry
            if (!string.IsNullOrEmpty(vacancy.industry))
            {
                if (!this.Industry.Equals(this.GetIndustry(vacancy.industry)))
                {
                    return false;
                }
            }
            #endregion

            #region Checking Education Level
            if (!string.IsNullOrEmpty(vacancy.education_level))
            {
                if (!this.EducationLevels.Contains(this.GetEducation(vacancy.education_level)))
                {
                    return false;
                }
            }
            #endregion

            #region Checking Skills
            foreach (VACANCY_SKILL skill in vacancy.VACANCY_SKILL)
            {
                if (string.IsNullOrEmpty(skill.optional) || skill.optional.Equals("N"))
                {
                    if (!this.ContainsSkill(skill.skill_id))
                        return false;
                }
            }
            #endregion
                
            return true;
        }

    }

    #region Enums
    public enum EducationLevel
    {
        HighSchool,
        AssociateDegree,
        Bsc,
        Msc,
        MBA,
        JD,
        MD,
        PHD,
        EngineersDegree,
        Other
    } 
    #endregion
}